﻿using CommonLib.Base;
using CommonLib.Util;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SqlConvertTool.DBContext;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Windows;
using System.Windows.Forms;

namespace SqlConvertTool;

public partial class MainViewModel : ObservableValidator
{
    public ObservableCollection<string> Files { get; set; }

    [ObservableProperty]
    [Required(ErrorMessage = "Source folder is Required..")]
    private string txtIn;

    [ObservableProperty]
    [Required(ErrorMessage = "Target folder is Required..")]
    private string txtOut;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(TxtPattern))]
    private string txtBefore;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(TxtPattern))]
    private string txtAfter;

    [ObservableProperty]
    private bool importData;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(Visbly))]
    private bool createScript;

    [ObservableProperty]
    private bool hasView;

    [ObservableProperty]
    private bool hasType;

    [ObservableProperty]
    private bool hasStore;

    public Visibility Visbly
    {
        get
        {
            if (CreateScript) return Visibility.Visible;
            else return Visibility.Hidden;
        }
    }

    [Required(ErrorMessage = "Before Language and After Language are Required..")]
    [SqlEquls]
    public string TxtPattern
    {
        get
        {
            if (string.IsNullOrEmpty(TxtBefore) || string.IsNullOrEmpty(TxtAfter)) return string.Empty;
            else return $"{TxtBefore} TO {TxtAfter}";
        }
    }

    [ObservableProperty]
    private string txtEncoding;

    [ObservableProperty]
    private Visibility wait;

    public BaseDBContext? BeforeContext { get; set; }

    public BaseDBContext? AfterContext { get; set; }

    public MainViewModel()
    {
        TxtIn = string.Empty;
        TxtOut = string.Empty;
        TxtBefore = string.Empty;
        TxtAfter = string.Empty;
        TxtEncoding = "UTF-8";
        HasStore = true;
        HasType = true;
        HasView = true;
        Files = new ObservableCollection<string>();
    }

    [RelayCommand]
    public void InPath()
    {
        var fd = new FolderBrowserDialog();
        DialogResult dr = fd.ShowDialog();
        if (dr == DialogResult.OK) TxtIn = fd.SelectedPath;
    }

    [RelayCommand]
    public void OutPath()
    {
        var fd = new FolderBrowserDialog();
        DialogResult dr = fd.ShowDialog();
        if (dr == DialogResult.OK) TxtOut = fd.SelectedPath;
    }

    [RelayCommand]
    public void TestConnect()
    {
        ValidateAllProperties();
        if (HasErrors) return;
        var conn = new DBConnect();
        var model = new ConnectModel(TxtBefore);
        conn.DataContext = model;
        conn.ShowDialog();
        BeforeContext = model.DBContext;
        ReadScriptCommand.NotifyCanExecuteChanged();
        ConvertCommand.NotifyCanExecuteChanged();
    }


    [RelayCommand(CanExecute = nameof(CanReadSql))]
    public void ReadScript()
    {
        if (BeforeContext == null)
        {
            InfoUtil.Warng("Test the dataBase link first");
            return;
        }
        if (ImportData)
        {
            var conn = new DBConnect();
            var model = new ConnectModel(TxtAfter);
            conn.DataContext = model;
            conn.ShowDialog();
            AfterContext = model.DBContext;
        }
        var msg = BeforeContext!.OutPutCreateScript(TxtIn);
        Wait = Visibility.Hidden;
        if (!string.IsNullOrEmpty(msg))
        {
            InfoUtil.Error(msg);
            return;
        }
        InfoUtil.Success("Create Script Success!");
    }

    //[RelayCommand(CanExecute = nameof(CanConvert))]
    [RelayCommand]
    public void Convert()
    {
        ConstUtil.InPath = TxtIn;
        ConstUtil.OutPath = TxtOut;
        ConstUtil.After = TxtAfter;
        ConstUtil.Encoding = TxtEncoding;
        Assembly assembly = Assembly.Load($"{TxtBefore}");
        var obj = assembly.CreateInstance($"{TxtBefore}.Read.{TxtBefore}FilesRead");
        if (obj != null && obj is SqlFilesRead reader)
        {
            reader.Read(Files, assembly);
            InfoUtil.Success("Sql Conversion is OK");
        }
    }

    [RelayCommand]
    public void Clear()
    {
        TxtIn = string.Empty;
        TxtOut = string.Empty;
        TxtBefore = string.Empty;
        TxtAfter = string.Empty;
        TxtEncoding = "UTF-8";
        HasStore = true;
        HasType = true;
        HasView = true;
        ImportData = false;
        CreateScript = false;
        Files.Clear();
        ReadScriptCommand.NotifyCanExecuteChanged();
        ConvertCommand.NotifyCanExecuteChanged();
    }

    private bool CanReadSql => BeforeContext != null && CreateScript;

    private bool CanConvert => BeforeContext != null;
}
